/**
 * This class describes the xml and the tags used to build the interfaces
 * There are currently two types of xml files:
 *   1 - A "combo box list" xml file that holds the list of other xml files
 *  and a short description of the files
 *   2 - A "dialog frame" xml file that holds the information about the frame and the
 * components needed to build the interface dialogs.
 */
//ENCODING OF XML FILES MUST BE UTF8!!!
package br.unb.plugins.geral.view;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Iterator;

import br.unb.core.traffic.Traffic;
import br.unb.plugins.geral.model.XmlComboItemModel;
import br.unb.plugins.geral.model.XmlComponentModel;
import br.unb.plugins.geral.model.XmlFrameModel;
import br.unb.plugins.geral.model.XmlTrafficConverter;
import br.unb.utils.Console;
import br.unb.utils.Path;
import br.unb.utils.Resource;

import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.converters.ConversionException;
//ENCODING OF XML FILES MUST BE UTF8!!!

public class XmlFactory {

    public XmlFactory() {
        Console.println("XmlFactory() <init>");
    }

    /**Xml file type one: combo List*/
    public static ArrayList getComboBoxListFromXml(String xmlName) {
        XStream xstream = new XStream();
        //tags that appear in this type of xml file
        xstream.alias("comboBox", ArrayList.class);
        xstream.alias("comboItem", XmlComboItemModel.class);

        return (ArrayList) loadXml(xstream, xmlName);
    }

    /**Xml file type two: frame description*/
    public static XmlFrameModel getFrameFromXml(String xmlName) {

        XStream xstream = new XStream();
        //Tags that appear in this type of xml file
        xstream.alias("frame", XmlFrameModel.class);
        xstream.alias("className", String.class);
        xstream.alias("panel", ArrayList.class);
        xstream.alias("panelLine", ArrayList.class);

        xstream.alias("component", XmlComponentModel.class);
        xstream.alias("values", ArrayList.class);
        //xstream.alias("rangeMin", String.class);
        //xstream.alias("rangeMax", String.class);
        xstream.alias("value", String.class);
        xstream.alias("validations", ArrayList.class);
        xstream.alias("validation", String.class);

        return (XmlFrameModel) loadXml(xstream, xmlName);
    }
    /**
     * Converts a string XML to a traffic
     * @param xml
     * @return
     *
    public static Traffic xml2Traffic(String xml) {
    }*/
    private static final XStream trafficStream;

    static {
        trafficStream = new XStream();
        trafficStream.registerConverter(new XmlTrafficConverter());
        trafficStream.alias("traffic", Traffic.class);
    }

    public static Traffic getTrafficFromXml(String xml) {
        try {
            return (Traffic) trafficStream.fromXML(xml);
        } catch (com.thoughtworks.xstream.converters.ConversionException e) {
            Console.printError(e.getMessage());
            Console.printError("CONVERSION_EXCEPTION_XML");
            return null;
        } catch (com.thoughtworks.xstream.io.StreamException e) {
            Console.printError(e.getMessage());
            Console.printError("ERROR_READING_XML");
            System.exit(-1);
            return null;
        }
    }

    /**
     * Converts a traffic object to a xml
     * @param traffic
     * @return string traffic serialized as xml
     *
    public static String traffic2Xml(Traffic traffic) {
    return xst.toXML(traffic);
    }*/
    public static String getXmlFromTraffic(Traffic t) {
        return trafficStream.toXML(t);
    }

    /**************** Private methods *********************/
    private static Object loadXml(XStream xstream, String xmlName) {
        try {
            InputStreamReader i =
                    new InputStreamReader(
                    new FileInputStream(
                    new File(Path.getXmlDir(), xmlName)), "UTF8");
            //ENCODING OF XML FILE MUST BE UTF8!!! or it will fail on the next line...
            return xstream.fromXML(i);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            Console.showMessageDialog(
                    Resource.getString("THE_FILE") + xmlName + Resource.getString("COULD_NOT_BE_FOUND") + Resource.getString("SUGESTIONS"));
        } catch (ConversionException e) {
            Console.showMessageDialog(
                    e.getShortMessage() + Resource.getString("THE_FILE") + xmlName + Resource.getString("COULD_NOT_BE_READ") + Resource.getString("SUGESTIONS"));
        } catch (UnsupportedEncodingException e) {
            Console.showMessageDialog(
                    Resource.getString("THE_FILE") + xmlName + Resource.getString("MUST_BE_UTF_8"));
        }
        return null;
    }

    public static Object getNewInstanceFromXML(String xmlName, String name) {
        ArrayList list = getComboBoxListFromXml(xmlName);
        Iterator entry = list.iterator();
        while (entry.hasNext()) {
            String distName = (String) entry.next();
            String classname = (String) entry.next();
            if (distName.equals(name)) {
                if (classname != null) {
                    try {
                        return Class.forName(classname).newInstance();
                    } catch (InstantiationException e) {
                        e.printStackTrace();
                        Console.println(
                                Resource.getString("THE_CLASS") + classname + Resource.getString("DO_NOT_HAVE_EMPTY_CONSTRUCTOR"));

                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                        Console.println(
                                Resource.getString("COULD_NOT_ACCESS_CLASS") + classname);
                    } catch (ClassNotFoundException e) {
                        e.printStackTrace();
                        Console.println(
                                Resource.getString("THE_CLASS") + classname + Resource.getString("NOT_FOUND") + Resource.getString("SUGESTION_VERIFY_XML"));

                    }
                }
            }
        }
        return null;
    }
}
